Skip to content

feat(learn): weight loops in Headroom Learn + RTK-loop eval#1160

Merged
JerrettDavis merged 4 commits into
headroomlabs-ai:mainfrom
purva-8:learn-loop-weighting
Jun 22, 2026
Merged

feat(learn): weight loops in Headroom Learn + RTK-loop eval#1160
JerrettDavis merged 4 commits into
headroomlabs-ai:mainfrom
purva-8:learn-loop-weighting

Conversation

@purva-8

@purva-8 purva-8 commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Description

headroom learn ranked recommendations by a single LLM-guessed estimated_tokens_saved with a flat hardcoded confidence, and had no notion of a loop. So (1) RTK re-fetch loops were invisible - RTK truncates a command's output, the agent re-runs larger-limit variants, those calls succeed (is_error=False), and analyze() even early-returned when a session had no failures and no events - and (2) even when surfaced, a loop ranked no higher than a one-off mistake. This adds loop-aware weighting plus the eval that reproduces an RTK loop, runs it through Learn, and checks the guardrail prevents re-triggering.

Closes #1159

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Performance improvement
  • Code refactoring (no functional changes)

Changes Made

  • New headroom/learn/loops.py: detect_loops() (canonical signature collapses RTK pagination/limit variants; classifies error vs rtk-refetch loops; measured wasted tokens), format_loops_for_digest(), apply_loop_weighting().
  • analyzer.py: detect loops up front (fixes the no-failure early-return), lead the digest with them, prioritize loops in the system prompt, re-sort after weighting.
  • models.py: Recommendation.is_loop_guardrail / loop_occurrences.
  • benchmarks/rtk_loop_learn_eval.py + headroom/learn/fixtures.py: the two-phase RTK-loop eval and its session fixtures.
  • Tests, docs/rtk-loop-weighting.md, CHANGELOG entry.

Testing

  • Unit tests pass (pytest)
  • Linting passes (ruff check .)
  • Type checking passes (mypy headroom) - not run (mypy not in my minimal env; see Not tested)
  • New tests added for new functionality
  • Manual testing performed

Test Output

$ python -m pytest tests/test_learn/ -q
190 passed, 3 skipped, 1 warning in 5.85s
$ ruff check <changed files>
All checks passed!

Real Behavior Proof

  • Environment: macOS (Darwin 25.0), Python 3.10.18, fresh venv (pip install -e minus the optional hnswlib/proxy extras, which are unrelated to learn); real LLM via the analyzer's claude CLI backend (HEADROOM_LEARN_CLI=claude, claude-cli 2.1.158) — no API key used.
  • Exact command / steps: HEADROOM_LEARN_CLI=claude python -c "from benchmarks.rtk_loop_learn_eval import run_eval; c=run_eval(use_real_llm=True); print(c.render())"
  • Observed result: the analyzer shelled out to a real model and produced the "Commands" guardrail quoted below, naming the looping command. The digest reports the measured 5,005-token waste and asks the model to rank loops first, so the model emitted that figure; in this run the guardrail ranked Add Claude Opus 4.5 and Claude 4 model family to context limits #1 and the scorecard was all-PASS (below). Caveat — real-mode is run-dependent: the rule's wording, and whether the post-hoc apply_loop_weighting fuzzy match fires, vary across runs (in one run it did not tag the rule). The deterministic CI eval (stub LLM) is the stable, reproducible artifact; this real run corroborates it.
  • Not tested: the analyzer's API-key path (ANTHROPIC/OPENAI/GEMINI) — exercised the equivalent claude CLI backend instead; mypy; a live agent obeying the written rule end-to-end (Phase 2 is a non-recurrence check, not a live agent — called out in the doc).

Real model output from this run, ranked #1 at the measured 5,005-token weight:

Commands — When grepping logs (or any large file), never loop with increasing | head -N limits — tool output is capped at ~4 KB regardless of N, so repeated attempts return identical bytes. Instead: redirect to a temp file (grep ... > /tmp/out.txt) then read it, or use grep -c first…

[PASS] loop_detected          (1 loop(s), ~5,005 tok wasted)
[PASS] guardrail_produced
[PASS] ranked_first
[PASS] names_command
[PASS] prescribes_fix
[PASS] weight_reflects_waste
[PASS] guardrail_holds
RESULT: PASS

(One real-mode run via the claude CLI backend. The deterministic pytest eval above is the stable artifact; see the run-dependence caveat under Observed result.)

The real run also caught an over-brittle check: an earlier names_command required the literal "TimeoutError"; the real model wrote a more general rule (grep + head -N) without it, so I fixed the check to verify the looping command is named, not an incidental literal.

Review Readiness

  • I have performed a self-review
  • This PR is ready for human review

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • I have updated the CHANGELOG.md if applicable

Additional Notes

  • No new dependencies. No network, no user/assistant content dropped — operates on already-captured session digests.
  • Kept as one logical change. mypy not run locally (minimal env); happy to address anything CI's mypy flags.

Headroom Learn ranked recommendations by a single LLM-guessed
estimated_tokens_saved with a flat hardcoded confidence, and had no
notion of a loop. Two consequences:

- RTK re-fetch loops were invisible: RTK truncates a command's output,
  so the agent re-runs larger-limit variants to fetch more. Those calls
  SUCCEED (is_error=False), and analyze() early-returned when a session
  had no failures and no events — skipping the loop entirely.
- Even when surfaced, a loop ranked no higher than a one-off mistake.

Add headroom/learn/loops.py:
- detect_loops(): group calls by a canonical signature that collapses
  RTK pagination/limit variants, flag >=3 repeats, classify error vs
  rtk-refetch loops, and compute MEASURED wasted tokens.
- format_loops_for_digest(): surface loops as a highest-priority digest
  section so the analyzer LLM sees them.
- apply_loop_weighting(): raise a matching recommendation's savings to
  at least the loop's measured waste and tag it as a loop guardrail, so
  loops outrank one-offs deterministically.

Wire into analyzer.py: detect loops up front (fixes the no-failure
early-return), lead the digest with them, prioritize loops in the system
prompt, and re-sort after weighting. Add is_loop_guardrail /
loop_occurrences to Recommendation.

Eval: benchmarks/rtk_loop_learn_eval.py reproduces the loop, runs learn,
scores the guardrail (produced/ranked-first/names-command/prescribes-fix/
weight-reflects-waste), then injects it and asserts a guarded session
does not re-trigger it. Deterministic in CI; real-LLM via --real.

Tests: tests/test_learn/test_loop_weighting.py (13) and
test_rtk_loop_eval.py. Design notes in docs/rtk-loop-weighting.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

PR governance

This PR follows the template and is marked ready for human review.

@github-actions github-actions Bot added the status: needs author action Pull request body or readiness checklist still needs author updates label Jun 19, 2026
@github-actions github-actions Bot added status: needs author action Pull request body or readiness checklist still needs author updates and removed status: needs author action Pull request body or readiness checklist still needs author updates labels Jun 19, 2026
@purva-8

purva-8 commented Jun 19, 2026

Copy link
Copy Markdown
Contributor Author

Correction (resolved). Disregard my CRLF diagnosis above — I had it wrong. The Test Output check was failing because my own PR body was submitted with CRLF line endings (a tooling round-trip on my end), not because GitHub forces CRLF or because the script is broken. Other PRs with LF bodies pass this check fine. Normalizing my body to LF cleared it, and the label is now status: ready for review.

The regex (\n after the fence tag) is still mildly fragile on CRLF input, but it's a latent edge case, not the blocker I claimed. Sorry for the noise.

…igure

The design doc stated the LLM 'rated the eval's loop at 150 tokens vs ~5,000
measured' as an empirical result. 150 was the deterministic stub's constant,
never a real model output — removed. Doc now states the implementation is a
hybrid (digest prompt hint + post-hoc fuzzy boost) and that the prompt hint is
currently load-bearing while the post-hoc boost is fuzzy-match-based and does
not always fire. Stub comment clarified as a simulated value.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@JerrettDavis JerrettDavis left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is not merge-ready yet. The body still says the review-readiness box is intentionally unchecked pending maintainer agreement, and GitHub reports mergeStateStatus=UNSTABLE rather than clean/green. Please mark it ready, ensure the required CI surface is green, and update the description once the approach is no longer pending.

@purva-8 purva-8 marked this pull request as ready for review June 20, 2026 19:32
@purva-8

purva-8 commented Jun 20, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @JerrettDavis - done:

  • Marked ready for review and checked the Review Readiness boxes.
  • Updated the description to drop the "pending maintainer agreement" wording.
  • Fixed the template/governance flag (it was my PR body having CRLF line endings - normalized to LF; label is now ready for review).

The only remaining non-green status is that 4 workflows are awaiting maintainer approval to run (first-time contributor) — CI, Wrap E2E, Init E2E, and Deploy Documentation, all currently action_required. I can't trigger those myself. Could a maintainer approve the run so CI can go green?

@purva-8 purva-8 requested a review from JerrettDavis June 20, 2026 19:34
@github-actions github-actions Bot added status: ready for review Pull request body is complete and the author marked it ready for human review and removed status: needs author action Pull request body or readiness checklist still needs author updates labels Jun 20, 2026
CI lint failed: headroom/learn/loops.py:197 no-untyped-def — the
recommendations param was untyped. Recommendation lives in models.py which
does not import loops, so there is no circular import; annotate it directly
as list[Recommendation] (removing the stale lazy-typing comment).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions github-actions Bot added status: has conflicts Pull request has merge conflicts with the base branch and removed status: ready for review Pull request body is complete and the author marked it ready for human review labels Jun 22, 2026
@github-actions github-actions Bot added status: ready for review Pull request body is complete and the author marked it ready for human review and removed status: has conflicts Pull request has merge conflicts with the base branch labels Jun 22, 2026

@JerrettDavis JerrettDavis left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed the current head after the main merge/type-annotation commit. The loop detection, digest surfacing, measured-waste weighting, and deterministic RTK-loop eval still look good, and the branch is clean with CI green.

@JerrettDavis JerrettDavis merged commit 14e8dc4 into headroomlabs-ai:main Jun 22, 2026
23 checks passed
studyzy pushed a commit to studyzy/headroom that referenced this pull request Jun 24, 2026
…labs-ai#1160)

## Description

`headroom learn` ranked recommendations by a single LLM-guessed
`estimated_tokens_saved` with a flat hardcoded `confidence`, and had
**no notion of a loop**. So (1) RTK re-fetch loops were invisible - RTK
truncates a command's output, the agent re-runs larger-limit variants,
those calls *succeed* (`is_error=False`), and `analyze()` even
early-returned when a session had no failures and no events - and (2)
even when surfaced, a loop ranked no higher than a one-off mistake. This
adds loop-aware weighting plus the eval that reproduces an RTK loop,
runs it through Learn, and checks the guardrail prevents re-triggering.

Closes headroomlabs-ai#1159

## Type of Change

- [ ] Bug fix (non-breaking change that fixes an issue)
- [x] New feature (non-breaking change that adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update
- [ ] Performance improvement
- [ ] Code refactoring (no functional changes)

## Changes Made

- New `headroom/learn/loops.py`: `detect_loops()` (canonical signature
collapses RTK pagination/limit variants; classifies error vs rtk-refetch
loops; **measured** wasted tokens), `format_loops_for_digest()`,
`apply_loop_weighting()`.
- `analyzer.py`: detect loops up front (fixes the no-failure
early-return), lead the digest with them, prioritize loops in the system
prompt, re-sort after weighting.
- `models.py`: `Recommendation.is_loop_guardrail` / `loop_occurrences`.
- `benchmarks/rtk_loop_learn_eval.py` + `headroom/learn/fixtures.py`:
the two-phase RTK-loop eval and its session fixtures.
- Tests, `docs/rtk-loop-weighting.md`, CHANGELOG entry.

## Testing

- [x] Unit tests pass (`pytest`)
- [x] Linting passes (`ruff check .`)
- [ ] Type checking passes (`mypy headroom`) - not run (mypy not in my
minimal env; see Not tested)
- [x] New tests added for new functionality
- [x] Manual testing performed

### Test Output

```text
$ python -m pytest tests/test_learn/ -q
190 passed, 3 skipped, 1 warning in 5.85s
$ ruff check <changed files>
All checks passed!
```

## Real Behavior Proof

- Environment: macOS (Darwin 25.0), Python 3.10.18, fresh venv (`pip
install -e` minus the optional `hnswlib`/proxy extras, which are
unrelated to `learn`); real LLM via the analyzer's claude CLI backend
(`HEADROOM_LEARN_CLI=claude`, claude-cli 2.1.158) — no API key used.
- Exact command / steps: `HEADROOM_LEARN_CLI=claude python -c "from
benchmarks.rtk_loop_learn_eval import run_eval;
c=run_eval(use_real_llm=True); print(c.render())"`
- Observed result: the analyzer shelled out to a real model and produced
the "Commands" guardrail quoted below, naming the looping command. The
digest reports the measured 5,005-token waste and asks the model to rank
loops first, so the model emitted that figure; in this run the guardrail
ranked **headroomlabs-ai#1** and the scorecard was all-PASS (below). Caveat — real-mode
is run-dependent: the rule's wording, and whether the post-hoc
`apply_loop_weighting` fuzzy match fires, vary across runs (in one run
it did not tag the rule). The **deterministic CI eval** (stub LLM) is
the stable, reproducible artifact; this real run corroborates it.
- Not tested: the analyzer's API-key path (ANTHROPIC/OPENAI/GEMINI) —
exercised the equivalent claude CLI backend instead; `mypy`; a live
agent *obeying* the written rule end-to-end (Phase 2 is a non-recurrence
check, not a live agent — called out in the doc).

Real model output from this run, ranked headroomlabs-ai#1 at the measured 5,005-token
weight:

> **Commands** — When grepping logs (or any large file), never loop with
increasing `| head -N` limits — tool output is capped at ~4 KB
regardless of N, so repeated attempts return identical bytes. Instead:
redirect to a temp file (`grep ... > /tmp/out.txt`) then read it, or use
`grep -c` first…

```text
[PASS] loop_detected          (1 loop(s), ~5,005 tok wasted)
[PASS] guardrail_produced
[PASS] ranked_first
[PASS] names_command
[PASS] prescribes_fix
[PASS] weight_reflects_waste
[PASS] guardrail_holds
RESULT: PASS
```

(One real-mode run via the claude CLI backend. The deterministic
`pytest` eval above is the stable artifact; see the run-dependence
caveat under Observed result.)

The real run also caught an over-brittle check: an earlier
`names_command` required the literal "TimeoutError"; the real model
wrote a *more general* rule (grep + `head -N`) without it, so I fixed
the check to verify the looping **command** is named, not an incidental
literal.

## Review Readiness

- [x] I have performed a self-review
- [x] This PR is ready for human review

## Checklist

- [x] My code follows the project's style guidelines
- [x] I have performed a self-review of my code
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [x] I have updated the CHANGELOG.md if applicable

## Additional Notes

- No new dependencies. No network, no user/assistant content dropped —
operates on already-captured session digests.
- Kept as one logical change. mypy not run locally (minimal env); happy
to address anything CI's mypy flags.

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: JD Davis <mxjerrett@gmail.com>
@github-actions github-actions Bot mentioned this pull request Jun 25, 2026
chopratejas pushed a commit that referenced this pull request Jun 29, 2026
🤖 I have created a release *beep* *boop*
---


<details><summary>0.28.0</summary>

##
[0.28.0](v0.27.0...v0.28.0)
(2026-06-29)


### Features

* add --disable-kompress-fallback to restore legacy PASSTHROUGH fallback
([#1185](#1185))
([f309244](f309244))
* add first-class OpenCode support (wrap, learn, mcp install)
([#559](#559))
([91cd210](91cd210))
* add HEADROOM_KEEPALIVE_EXPIRY to keep upstream connections warm
([#1124](#1124))
([85786b3](85786b3))
* **azure-foundry:** derive upstream URL from ANTHROPIC_FOUNDRY_RESOURCE
([#1138](#1138))
([e5031b0](e5031b0))
* **cache:** attribute prompt-cache misses to TTL lapse vs prefix change
([#1313](#1313))
([#1343](#1343))
([4658721](4658721))
* **code:** add Perl support to code-aware compressor
([#1125](#1125))
([f39858c](f39858c))
* headroom wrap opencode / unwrap opencode CLI
([#1105](#1105))
([b4571cc](b4571cc))
* **learn:** weight loops in Headroom Learn + RTK-loop eval
([#1160](#1160))
([14e8dc4](14e8dc4))
* **learn:** write per-project learnings to CLAUDE.local.md by default
([#1115](#1115))
([ced75e4](ced75e4))
* **proxy:** add request timeout config
([#738](#738))
([c0745d4](c0745d4))
* **proxy:** pilot hardening — inbound auth, security headers, audit
log, air-gap switch
([#1537](#1537))
([546ab55](546ab55))
* **proxy:** support glob patterns in exclude_tools
([#870](#870))
([#1259](#1259))
([a2159c0](a2159c0))
* **read-maturation:** activity-based hold-back Read maturation
(Mechanism B)
([#1068](#1068))
([723b80c](723b80c))
* **savings:** durable savings ledger + headroom savings command
([#1127](#1127))
([978ffa0](978ffa0))
* **wrap:** add --1m to preserve the 1M context window on wrap claude
([#1158](#1158))
([#1351](#1351))
([b50d9c1](b50d9c1))
* **wrap:** make tokensave the primary coding-task compressor, Serena
the backup
([#1230](#1230))
([dca9853](dca9853))


### Bug Fixes

* **agent-evals:** Phase 0 — coding-agent accuracy A/B framework
([#1037](#1037))
([84f9871](84f9871))
* **agno:** tolerate streaming tool-call SDK objects in parser
([#1312](#1312))
([#1336](#1336))
([5986c22](5986c22))
* **bedrock:** add boto3 1.41 + CRT for aws login credentials
([#1486](#1486))
([4db3bc9](4db3bc9))
* bump codebase-memory-mcp to v0.8.1
([#1284](#1284))
([530318b](530318b))
* **ccr:** make headroom_retrieve a hash-only full-content lookup
([#1532](#1532))
([c2fc4d3](c2fc4d3))
* **ccr:** propagate --no-ccr-marker flag to all compressors
([#1022](#1022))
([#1197](#1197))
([0c9b42a](0c9b42a))
* **ccr:** skip Anthropic marker emission when tool injection is
deferred
([#1273](#1273))
([2cae13d](2cae13d))
* **ci:** extend gitleaks allowlist to cover test fixtures + verified
examples
([#1539](#1539))
([d2565a6](d2565a6))
* **ci:** guarantee model present in test shards to end cache-miss
flakiness
([#1399](#1399))
([2e29c72](2e29c72))
* **ci:** normalize Windows CRLF line endings in PR governance script
([#1012](#1012))
([5194388](5194388))
* **cli:** add explicit UTF-8 encoding to file I/O in wrap commands
([#1126](#1126))
([#1164](#1164))
([a0cb798](a0cb798))
* **cli:** fall back gracefully when embedding-server sidecar is absent
([#1206](#1206))
([38f1404](38f1404))
* **cli:** harden all CLI surfaces + fix docs accuracy
([#1491](#1491))
([bd76235](bd76235))
* **cli:** wire --http2/--no-http2 (HEADROOM_HTTP2) into proxy command
([#1373](#1373))
([e06b616](e06b616))
* **cli:** wire --rpm/--tpm and HEADROOM_RPM/HEADROOM_TPM to the Click
proxy command
([#1375](#1375))
([8aab8f2](8aab8f2))
* **code:** slice tree-sitter byte offsets as UTF-8
([#1332](#1332))
([8238402](8238402))
* **code:** validate Python compressed syntax
([#1302](#1302))
([cbd361d](cbd361d))
* **code:** verify a real parse in tree-sitter availability check
([#1231](#1231))
([#1299](#1299))
([5e0bb69](5e0bb69))
* **codex:** retag threads on init so Codex Desktop history stays
visible ([#961](#961))
([#1349](#1349))
([e6bbc40](e6bbc40))
* **codex:** stop pinning Codex memory MCP to one project db
([#1269](#1269))
([ad7993b](ad7993b))
* **dashboard:** include RTK stats in the historical tab
([#1324](#1324))
([35939c3](35939c3))
* **deps:** remediate dependency CVEs and publish SBOM
([#1509](#1509))
([5771a80](5771a80))
* **docker:** persist session history across container revisions
([#1118](#1118))
([5912d65](5912d65))
* **gemini:** offload compression to the executor
([#1382](#1382))
([615848e](615848e))
* **gemini:** resolve Google model capabilities through ModelRegistry
([#1276](#1276))
([17ecad9](17ecad9))
* **install:** guard install_agent_ensure against duplicate runtime
spawns
([#1301](#1301))
([8da0b4e](8da0b4e))
* **install:** repair macOS launchd restart/start lifecycle
([#1290](#1290))
([da1a397](da1a397))
* **install:** stop duplicating ENTRYPOINT in persistent-docker runtime
command ([#833](#833))
([#1348](#1348))
([feedead](feedead))
* **io:** use UTF-8 with locale fallback and preserve line endings on
config/text I/O
([#1498](#1498))
([1baa04e](1baa04e))
* **kompress:** hard override keeps must-keep tokens regardless of model
score ([#1400](#1400))
([42612c8](42612c8))
* **langchain:** disable streaming on wrapped model during ainvoke()
([#1287](#1287))
([3590046](3590046))
* **mcp:** register managed installs with a resolvable headroom command
([#1386](#1386))
([22def93](22def93))
* **mcp:** report correct savings_percent in headroom_compress
([#1106](#1106))
([f216e43](f216e43))
* **opencode:** write local MCP config
([#1381](#1381))
([6c83790](6c83790))
* **packaging:** move hnswlib to optional [vector] extra so [all] needs
no C++ toolchain
([#1499](#1499))
([80fa086](80fa086))
* patch rtk hook script to use absolute path after register_claude_hooks
([#571](#571))
([b618d2d](b618d2d))
* **perf:** surface RTK/CLI context-tool savings in perf and the session
card ([#1433](#1433))
([9362747](9362747))
* **proxy:** add --protect-tool-results to prevent lossy compression of
exact-output Bash results
([#1374](#1374))
([51d4bcf](51d4bcf))
* **proxy:** add an Anthropic buffered read-timeout override
([#1331](#1331))
([3be2526](3be2526))
* **proxy:** add versionless Vertex AI routes for Claude Code
compatibility
([#1321](#1321))
([bb3e040](bb3e040))
* **proxy:** bind before eager preload so a hung compressor load can't
block startup
([#1500](#1500))
([d5ac07f](d5ac07f))
* **proxy:** build SSL contexts for custom CA bundles
([#1134](#1134))
([561ba17](561ba17))
* **proxy:** forward request-id headers on the streaming path
([#1100](#1100))
([#1258](#1258))
([3d59df7](3d59df7))
* **proxy:** gate CCR retrieve/compress endpoints to loopback
([#1338](#1338))
([acafb2d](acafb2d))
* **proxy:** honor force_kompress routing profile
([#996](#996))
([b4682d6](b4682d6))
* **proxy:** keep large compression results on the critical path
([#296](#296))
([#1352](#1352))
([90734b6](90734b6))
* **proxy:** offload /v1/compress to the compression executor to stop
blocking the loop
([#1501](#1501))
([27e010e](27e010e))
* **proxy:** preserve Responses memory continuations with store=false
([#1103](#1103))
([cdfeeac](cdfeeac))
* **proxy:** queue mid-turn user messages on non-Bedrock streaming path
([#1377](#1377))
([b09f027](b09f027))
* **proxy:** register interceptor in explicit transforms list when
HEADROOM_INTERCEPT_ENABLED
([#1376](#1376))
([55c700c](55c700c))
* **proxy:** report real input tokens on streaming message_start
([#1132](#1132))
([#1305](#1305))
([70cc96a](70cc96a))
* **proxy:** retry upstream 429 with Retry-After on both forwarders
([#1329](#1329))
([90bee89](90bee89))
* **proxy:** retry upstream 529 overloaded like 429 on both forwarders
([#1495](#1495))
([547b15d](547b15d))
* **proxy:** stop re-compressing headroom_retrieve output and emitting
unredeemable markers
([#1323](#1323))
([43494ff](43494ff))
* **proxy:** strip Codex lite header from OpenAI WebSockets
([#1543](#1543))
([5d3803a](5d3803a))
* **read-lifecycle:** persist STALE Read originals in the CCR store
([#1488](#1488))
([9157173](9157173))
* recover persistent proxy feature checks and reject non-Copilot
exchange URL
([#1465](#1465))
([16c638b](16c638b))
* remove agents.md
([#1540](#1540))
([a7d3360](a7d3360))
* respect COPILOT_PROVIDER_TYPE env var when provider_type is auto
([#549](#549))
([24cf256](24cf256))
* restore token-mode compression on frozen prefixes
([#1489](#1489))
([8e0dadf](8e0dadf))
* **router:** degrade to pure-Python detection on native panic
([#1123](#1123))
([#1260](#1260))
([a00fb67](a00fb67))
* **rtk:** stop hook registration timing out on a forked daemon
([#1314](#1314))
([9758817](9758817))
* **smart-crusher:** honor enable_ccr_marker on the opaque-blob path
([#1130](#1130))
([27d6f8e](27d6f8e))
* **subscription:** only reset 5h contribution on real rollover, not API
jitter
([#1255](#1255))
([8d6c175](8d6c175))
* **subscription:** run transcript token scan off the event loop
([#1263](#1263))
([f03021f](f03021f))
* surface output reduction without a restart, and explain $0.00 savings
on Python 3.14
([#1296](#1296))
([c30ec4c](c30ec4c))
* **tests:** reset whole headroom logger subtree so caplog stays
deterministic
([#1117](#1117))
([fda4670](fda4670))
* **tls:** add HEADROOM_TLS_STRICT=0 toggle for corporate SSL inspection
([#1308](#1308))
([#1341](#1341))
([52068dd](52068dd))
* **tokenizers:** price CJK/Kana/Hangul at ~1 token per char in
EstimatingTokenCounter
([#1093](#1093))
([a35fe86](a35fe86))
* **transforms:** gate tool string output from lossy compression
([#1307](#1307))
([#1387](#1387))
([c6c921a](c6c921a))
* **websocket:** harden responses websocket origin handling
([#1481](#1481))
([c632023](c632023))
* **windows:** pin UTF-8 encoding on text-mode subprocess calls
([#1311](#1311))
([d633e81](d633e81))
* **wrap:** add Copilot unwrap command
([#1251](#1251))
([b4fde0c](b4fde0c))
* **wrap:** isolate proxy stdio from proxy.log on Windows
([#1191](#1191))
([959ab0d](959ab0d))
* **wrap:** keep agent savings opt-in
([#1294](#1294))
([b829ceb](b829ceb))
* **wrap:** show the dashboard URL when the proxy is already running
([#1313](#1313))
([b0146c4](b0146c4))


### Performance Improvements

* **compression:** take large cold-start contexts off the synchronous
kompress path
([#1171](#1171))
([#1298](#1298))
([6c68ff4](6c68ff4))
</details>

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status: ready for review Pull request body is complete and the author marked it ready for human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(learn): weight loops in Headroom Learn

2 participants